﻿using Stylet;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WriteBugs.Library.Model;

namespace WriteBugs.Controls
{
    /// <summary>
    /// ListViewAdv.xaml 的交互逻辑
    /// </summary>
    public partial class ListViewAdv : UserControl
    {
        public ListViewAdv()
        {
            InitializeComponent();
        }

        #region 属性
        public BindableCollection<ListViewAdvNodeItem> ListViewAdvNodeItems
        {
            get { return (BindableCollection<ListViewAdvNodeItem>)GetValue(ListViewAdvNodeItemProperty); }
            set { SetValue(ListViewAdvNodeItemProperty, value); }
        }

        public static readonly DependencyProperty ListViewAdvNodeItemProperty
            = DependencyProperty.Register("ListViewAdvNodeItems", typeof(BindableCollection<ListViewAdvNodeItem>), typeof(ListViewAdv), new UIPropertyMetadata(null, ListViewAdvNodeItemsPropertyChanged));

        private static void ListViewAdvNodeItemsPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs arg)
        {
            ListViewAdv? control = obj as ListViewAdv;
            BindableCollection<ListViewAdvNodeItem> Data = (BindableCollection<ListViewAdvNodeItem>)arg.NewValue;

            if (control != null && Data != null)
            {
                control.listView.ItemsSource = Data;
            }
        }


        public ListViewAdvNodeItem SelectedItem
        {
            get { return (ListViewAdvNodeItem)GetValue(SelectedItemItemProperty); }
            set { SetValue(SelectedItemItemProperty, value); }
        }

        public static readonly DependencyProperty SelectedItemItemProperty
            = DependencyProperty.Register("SelectedItem", typeof(ListViewAdvNodeItem), typeof(ListViewAdv), new UIPropertyMetadata(null, SelectedItemPropertyChanged));

        private static void SelectedItemPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs arg)
        {

        }

        #endregion

        #region 选择
        public static readonly RoutedEvent _SelectedItemChanged
         = EventManager.RegisterRoutedEvent("SelectedItemChanged", RoutingStrategy.Bubble, typeof(ListViewAdvSelectedItemChangesRoutedEventHandler), typeof(ListViewAdv));
        public event ListViewAdvSelectedItemChangesRoutedEventHandler SelectedItemChanged
        {
            add
            {
                AddHandler(_SelectedItemChanged, value);
            }
            remove
            {
                RemoveHandler(_SelectedItemChanged, value);
            }
        }

        private void listView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.listView.SelectedItem != null)
            {
                SelectedItem = this.listView.SelectedItem as ListViewAdvNodeItem;

                ListViewAdvSelectedItemChangesRoutedEventArgs args = new ListViewAdvSelectedItemChangesRoutedEventArgs(_SelectedItemChanged, this)
                {
                    SelectedItem = this.listView.SelectedItem as ListViewAdvNodeItem,
                };
                this.RaiseEvent(args);
            }
        }
        #endregion

        #region 删除
        public static readonly RoutedEvent _ItemDeleted
         = EventManager.RegisterRoutedEvent("ItemDeleted", RoutingStrategy.Bubble, typeof(ListViewAdvItemDeletedRoutedEventHandler), typeof(ListViewAdv));
        public event ListViewAdvItemDeletedRoutedEventHandler ItemDeleted
        {
            add
            {
                AddHandler(_ItemDeleted, value);
            }
            remove
            {
                RemoveHandler(_ItemDeleted, value);
            }
        }

        private void Delete_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (this.listView.SelectedItem != null)
            {
                ListViewAdvItemDeletedRoutedEventArgs args = new ListViewAdvItemDeletedRoutedEventArgs(_ItemDeleted, this)
                {
                    DeletedItem = this.listView.SelectedItem as ListViewAdvNodeItem,
                };

                this.RaiseEvent(args);
            }
        }
        #endregion

        #region MouseDoubleClick

        public static readonly RoutedEvent _DoubleClick
        = EventManager.RegisterRoutedEvent("DoubleClick", RoutingStrategy.Bubble, typeof(ListViewAdvDoubleClickRoutedEventHandler), typeof(ListViewAdv));
        public event ListViewAdvDoubleClickRoutedEventHandler DoubleClick
        {
            add
            {
                AddHandler(_DoubleClick, value);
            }
            remove
            {
                RemoveHandler(_DoubleClick, value);
            }
        }


        private void listView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (this.listView.SelectedItem != null)
            {
                ListViewAdvDoubleClickRoutedEventArgs args = new ListViewAdvDoubleClickRoutedEventArgs(_DoubleClick, this)
                {
                    DoubleClickedItem = this.listView.SelectedItem as ListViewAdvNodeItem,
                };

                this.RaiseEvent(args);
            }
        }


        #endregion

        #region StartDrag

        public bool CanStartDrag
        {
            get { return (bool)GetValue(CanStartDragProperty); }
            set { SetValue(CanStartDragProperty, value); }
        }

        public static readonly DependencyProperty CanStartDragProperty
            = DependencyProperty.Register("CanStartDrag", typeof(bool), typeof(ListViewAdv), new UIPropertyMetadata(false, null));

        private void listView_MouseMove(object sender, MouseEventArgs e)
        {
            if(!CanStartDrag)
            {
                return;
            }

            if (sender is ListView listview && e.LeftButton == MouseButtonState.Pressed && listview.SelectedItem != null)
            {
                DragDrop.DoDragDrop(listview, listview.SelectedItem, DragDropEffects.Move);
            }
        }

        private void CloseAdorners()
        {
            //关闭装饰器
            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.listView);
            if (adornerLayer != null)
            {
                Adorner[] adorners = adornerLayer.GetAdorners(this.listView);
                if (adorners != null)
                {
                    foreach (var adorner in adorners)
                    {
                        adornerLayer.Remove(adorner);
                    }
                }
            }
        }

        #endregion

        #region Dragged

        public DragInfo DragInfo
        {
            get { return (DragInfo)GetValue(DragInfoProperty); }
            set { SetValue(DragInfoProperty, value); }
        }

        public static readonly DependencyProperty DragInfoProperty =
            DependencyProperty.Register("DragInfo", typeof(DragInfo), typeof(ListViewAdv), new UIPropertyMetadata(null, null));

        public static readonly RoutedEvent _Dragged
           = EventManager.RegisterRoutedEvent("Dragged", RoutingStrategy.Bubble, typeof(ListViewAdvDraggedRoutedEventHandler), typeof(ListViewAdv));
        public event ListViewAdvDraggedRoutedEventHandler Dragged
        {
            add
            {
                AddHandler(_Dragged, value);
            }
            remove
            {
                RemoveHandler(_Dragged, value);
            }
        }

        private void listView_DragOver(object sender, DragEventArgs e)
        {
            bool ShowSpacing = false;
            e.Effects = DragDropEffects.None;
            if (e.Data.GetData(typeof(ListViewAdvNodeItem)) is ListViewAdvNodeItem fromItem)
            {
                if (e.OriginalSource is TextBlock txtTitle)
                {
                    if (txtTitle.Tag is Excerpt excerpt)
                    {
                        if (excerpt != null
                            && fromItem.Excerpt != null
                            && excerpt.ExcerptType == ExcerptType.Catalog
                            && excerpt != fromItem.Excerpt)
                        {
                            e.Effects = DragDropEffects.Move;
                        }
                    }
                }

                if (e.OriginalSource is ScrollViewer)
                {
                    ShowSpacing = true;
                    e.Effects = DragDropEffects.Move;
                }

                //显示Title装饰器
                AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.listView);
                if (adornerLayer != null)
                {
                    Adorner[] adorners = adornerLayer.GetAdorners(this.listView);
                    if (adorners != null)
                    {
                        foreach (var adorner in adorners)
                        {
                            adornerLayer.Remove(adorner);
                        }
                    }

                    Point pos = e.GetPosition(this.listView);
                    DragTitleAdorner _title = new DragTitleAdorner(this.listView, pos, fromItem.Excerpt?.Title);
                    adornerLayer.Add(_title);

                    if (ShowSpacing)
                    {
                        int index = (int)((pos.Y + 5) / 35);
                        int Count = this.listView.Items.Count;
                        if (index > Count)
                        {
                            index = Count;
                        }

                        SpacingAdorner spacing = new SpacingAdorner(this.listView, index);
                        adornerLayer.Add(spacing);
                    }
                }
            }

            e.Handled = true;
        }

        private void listView_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetData(typeof(ListViewAdvNodeItem)) is ListViewAdvNodeItem)
            {
                if (e.OriginalSource is TextBlock txtTitle)
                {
                    if (txtTitle.Tag is Excerpt excerpt)
                    {
                        if (excerpt.ExcerptType == ExcerptType.Catalog)
                        {
                            txtTitle.FontWeight = FontWeights.Bold;
                        }
                    }
                }
            }
        }

        private void listView_DragLeave(object sender, DragEventArgs e)
        {
            if (e.Data.GetData(typeof(ListViewAdvNodeItem)) is ListViewAdvNodeItem)
            {
                if (e.OriginalSource is TextBlock txtTitle)
                {
                    if (txtTitle.Tag is Excerpt)
                    {
                        txtTitle.FontWeight = FontWeights.Normal;
                    }
                }

                CloseAdorners();
            }
        }

        private void listView_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetData(typeof(ListViewAdvNodeItem)) is ListViewAdvNodeItem fromNode)
            {
                if (e.OriginalSource is TextBlock txtTitle)
                {
                    if (txtTitle.Tag is Excerpt toExcerpt)
                    {
                        txtTitle.FontWeight = FontWeights.Normal;

                        DragInfo = new DragInfo
                        {
                            SourceExcerpt = fromNode?.Excerpt,
                            TargetExcerpt = toExcerpt,
                        };

                        ListViewAdvDraggedRoutedEventArgs args = new(_Dragged, this.listView)
                        {
                            DragInfo = DragInfo,
                        };
                        RaiseEvent(args);

                        CloseAdorners();
                    }
                }

                if (e.OriginalSource is ScrollViewer)
                {
                    Point pos = e.GetPosition(this.listView);
                    int index = (int)((pos.Y + 5) / 35);
                    int Count = this.listView.Items.Count;
                    if (index > Count)
                    {
                        index = Count;
                    }

                    DragInfo = new DragInfo
                    {
                        DragType = DragType.SourceMove,
                        SourceExcerpt = fromNode?.Excerpt,
                        MoveToIndex = index,
                    };

                    ListViewAdvDraggedRoutedEventArgs args = new(_Dragged, this.listView)
                    {
                        DragInfo = DragInfo,
                    };
                    RaiseEvent(args);

                    CloseAdorners();
                }
            }
        }

        #endregion
    }
}
